package com.rpa.server.servicerpaserver.crawler.operate;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.rpa.secure.servicerpasecure.common.constant.MessageConstant;
import com.rpa.secure.servicerpasecure.common.constant.ParameterConstant;
import com.rpa.secure.servicerpasecure.common.constant.UrlConstant;
import com.rpa.secure.servicerpasecure.common.exception.TaskException;
import com.rpa.secure.servicerpasecure.common.util.CurrentTeacherInfoUtil;
import com.rpa.server.servicerpaserver.crawler.entity.Active;
import com.rpa.server.servicerpaserver.crawler.entity.User;
import com.rpa.server.servicerpaserver.crawler.entity.Work;
import com.rpa.server.servicerpaserver.crawler.entity.dto.ActiveDto;
import com.rpa.server.servicerpaserver.crawler.entity.dto.WorkDto;
import com.rpa.server.servicerpaserver.crawler.service.UserService;
import com.rpa.server.servicerpaserver.crawler.service.WorkService;
import com.rpa.server.servicerpaserver.util.CookieSerialize;
import com.rpa.server.servicerpaserver.util.WebDriverUtil;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName WorkOperate
 * @Description TODO
 * @Author 86152
 * @Date 2025/2/4 15:20
 * @Version 1.0
 **/
@Slf4j
@Component
public class WorkOperate {
    @Autowired
    private CookieSerialize cookieSerialize;
    @Autowired
    private UserService uerService;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private WorkService workService;

    @Async("workTaskExecutor")
    public CompletableFuture<Boolean> getWork(WorkDto workDto) {
        log.info("获取作业信息");

        // 校验用户是否存在
        User user = uerService.getById(workDto.getAccountId());
        if (user == null) {
            throw new TaskException(MessageConstant.NO_USER);
        }
        Map stringObjectMap = BeanUtil.beanToMap(workDto);

        // 调用异步方法获取班级id
        CompletableFuture<List<Map>> classIdsFuture = this.getWorkList(stringObjectMap);

        // 异步任务处理，等待结果
        classIdsFuture.thenAccept(classIds -> {
            try {
                if (CollUtil.isEmpty(classIds)) {
                    log.error(MessageConstant.SIGN_NULL);
                    return;
                }
                classIds.forEach(classId -> {
                    Map objectObjectHashMap = new HashMap<>() {{
                        putAll(stringObjectMap);
                        putAll(classId);
                    }};
                    handleSingleClass(objectObjectHashMap);
                });
            } catch (TaskException e) {
                // 记录日志或采取其他措施
                log.error("处理作业信息时发生错误: {}", e.getMessage(), e);
            }
        }).exceptionally(throwable -> {
            // 处理所有未捕获的异常
            log.error("异步任务中发生未知错误: {}", throwable.getMessage(), throwable);
            return null; // 或者返回一个默认值
        });


        return CompletableFuture.completedFuture(true); // 这里可以返回处理的状态，如果有需要
    }

    @Async("workListTaskExecutor")
    public CompletableFuture<List<Map>> getWorkList(Map map) {
        ChromeOptions options = new ChromeOptions();
        WebDriverUtil.setupWebDriver(options);
        ChromeDriver chromeDriver = null;
        List<Map> arrayList = new ArrayList<>();
        String accountId = MapUtil.getStr(map, "accountId", "");
        String courseId = MapUtil.getStr(map, "courseId", "");
        String clazzId = MapUtil.getStr(map, "classId", "");
        try {
            chromeDriver = new ChromeDriver(options);
            cookieSerialize.goFZF(accountId+"WORK", ParameterConstant.ROUTE_WIDGET,chromeDriver);
            chromeDriver.get(StrUtil.format(UrlConstant.HOMEWORK_LIST,courseId,clazzId));
            cookieSerialize.delAfterSaveCookies(accountId+"WORK", chromeDriver.manage().getCookies());
            WebDriverWait webDriverWait = new WebDriverWait(chromeDriver, Duration.ofSeconds(5));
            webDriverWait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//*/ul/*/div[1]/div")));

            List<WebElement> elements = chromeDriver.findElements(By.xpath("//*/ul/*/div[1]/div"));
            for (WebElement workElement : elements) {
                Map<String, String> workMap = new HashMap<>();
                WebElement h2Element = workElement.findElement(By.xpath("./div[1]/h2"));
                String onclickValue = h2Element.getAttribute("onclick");
                String workName= h2Element.getText();
                workMap.put( "workName",workName);
                WebElement element = workElement.findElement(By.xpath("./p/span"));
                String workTime = element.getText();
                workMap.put( "workTime",workTime);
                String[] parts = onclickValue.split("'");
                if (parts.length > 3) {
                    String workId = parts[3];
                    workMap.put( "workId",workId);
                } else {
                    log.error("获取workId失败");
                }
                arrayList.add(workMap);
            }

        } catch (Exception e) {
            log.error("获取作业列表信息失败", e);
            return CompletableFuture.completedFuture(arrayList);
        } finally {
            if (chromeDriver != null) {
                chromeDriver.quit();
            }
        }
        return CompletableFuture.completedFuture(arrayList);
    }

    @Async("workDetailTaskExecutor")
    public List<Work> getWorkDetail(Map map) {
        ChromeOptions options = new ChromeOptions();
        WebDriverUtil.setupWebDriver(options);
        ChromeDriver chromeDriver = null;
        List<Work> arrayList = new ArrayList<>();
        String accountId = MapUtil.getStr(map, "accountId", "");
        String workId = MapUtil.getStr(map, "workId", "");
       // String workName = MapUtil.getStr(map, "workName", "");
        String courseId = MapUtil.getStr(map, "courseId", "");
        String classId = MapUtil.getStr(map, "classId", "");
        try {
            chromeDriver = new ChromeDriver(options);
            cookieSerialize.goFZF(accountId+"WORK", ParameterConstant.ROUTE_WIDGET,chromeDriver);
            chromeDriver.get(StrUtil.format(UrlConstant.HOMEWORK_DETAIL, courseId,classId,workId,ParameterConstant.TRUE));
            cookieSerialize.delAfterSaveCookies(accountId, chromeDriver.manage().getCookies());
            List<Work> elementWork = this.getElementWork(map, chromeDriver,true);
            cookieSerialize.goFZF(accountId+"WORK", ParameterConstant.ROUTE_WIDGET,chromeDriver);
            chromeDriver.get(StrUtil.format(UrlConstant.HOMEWORK_DETAIL, courseId,classId,workId,ParameterConstant.FALSE));
            cookieSerialize.delAfterSaveCookies(accountId, chromeDriver.manage().getCookies());
            List<Work> elementWork1 = this.getElementWork(map, chromeDriver,false);
            arrayList.addAll(elementWork);
            arrayList.addAll(elementWork1);
        }catch (Exception e) {
            log.error("获取作业详细信息失败", e);
           // throw new TaskException(MessageConstant.GET_WORK_ERROR);
        }finally {
            if (chromeDriver != null) {
                chromeDriver.quit();
            }
        }
        return arrayList;
    }
    @Transactional
    public void handleSingleClass(Map objectObjectHashMap) {
        List<Work> classNameList = this.getWorkDetail(objectObjectHashMap);
        if (CollUtil.isEmpty(classNameList)) {
            throw new TaskException(MapUtil.getStr(objectObjectHashMap, "workId")+MessageConstant.WORKSPACE_NULL);
        }
        // 批量更新作业信息
        RLock lock = redissonClient.getLock(objectObjectHashMap.get("workId").toString());
        try{
            if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {
                this.deleteWork(objectObjectHashMap);
                workService.saveBatch(classNameList);
            }else{
                log.error("获取锁失败");
            }
        }catch (InterruptedException e) {
            log.error("获取锁失败", e);
        }finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    public Boolean deleteWork(Map objectObjectHashMap) {
        LambdaUpdateWrapper<Work> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(Work::getWorkId,MapUtil.getStr(objectObjectHashMap, "workId", ""));
        return workService.remove(lambdaUpdateWrapper);
    }

    public  List<Work> getElementWork(Map map, ChromeDriver chromeDriver, boolean isSubmit){
        String accountId = MapUtil.getStr(map, "accountId", "");
        String workId = MapUtil.getStr(map, "workId", "");
        String courseId = MapUtil.getStr(map, "courseId", "");
        String classId = MapUtil.getStr(map, "classId", "");
        String workName = MapUtil.getStr(map, "workName", "");
        String workTime = MapUtil.getStr(map, "workTime", "");
        List<Work> arrayList = new ArrayList<>();
        try {
            WebDriverWait webDriverWait = new WebDriverWait(chromeDriver, Duration.ofSeconds(5));
            webDriverWait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("/html/body/div")));
            String text = chromeDriver.findElement(By.xpath("/html/body/div")).getText();
            if("暂无数据".equals(text)){
                return arrayList;
            }
        }catch (Exception e){
            WebDriverWait webDriverWait = new WebDriverWait(chromeDriver, Duration.ofSeconds(5));
            webDriverWait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//ul[@class='dataBody_td']")));
            List<WebElement> elements = chromeDriver.findElements(By.xpath("//ul[@class='dataBody_td']"));
            for (WebElement element : elements){
                Work work=new Work();
                work.setWorkId(workId);
                work.setAccountId(accountId);
                work.setCourseId(courseId);
                work.setClazzId(classId);
                work.setWorkName(workName);
                work.setWorkTime(workTime);
                WebElement userName = element.findElement(By.xpath(".//li[2]/div[@class='py_name']"));
                work.setUserName(userName.getText());
                WebElement studentNumber = element.findElement(By.xpath(".//li[3]"));
                work.setStudentNumber(studentNumber.getText());
                WebElement submitTime = element.findElement(By.xpath(".//li[4]"));
                work.setSubmitTime(submitTime.getText());
                if (isSubmit){
                    WebElement score = element.findElement(By.xpath(".//li[8]/input"));
                    work.setScore(Double.parseDouble(StrUtil.isNotEmpty(score.getAttribute("value"))? score.getAttribute("value") : "0"));
                }else {
                    work.setScore(Double.parseDouble("0"));
                }
                arrayList.add(work);
            }
            return arrayList;
        }
        return arrayList;
    }

}
